package memorphic.utils
{
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	import mx.logging.Log;

	use namespace flash_proxy
	
	dynamic public class SWFLoader extends Proxy implements IEventDispatcher
	{
		private var __uri:String;
		private var __byteArray:ByteArray;
		 
		public var AVM_version:uint;
		public var content:Sprite = new Sprite();
		private var controller:*;		
		private var __dispatcher:EventDispatcher;
		
		public function SWFLoader():void
		{
			__dispatcher = new EventDispatcher(this);
		}
		override flash_proxy  function callProperty(name:*, ...rest):* {
    		try{
    			var s:String = name.localName;
				if(controller == null && AVM_version == 2)
				{
					controller = (content.getChildAt(0) as Loader).content;
				}
	    		(controller[s]  as Function).apply(controller,rest);
    		}
    		catch(e:Error)
    		{
    			
    		}
	    }
	     override flash_proxy  function getProperty(name:*):* {
	      	 var p:*  = function():*
	         {
	         	p[name].apply(arguments);
	         }
	         return p;	        
	    }
	    override flash_proxy  function setProperty(name:*, value:*):void 
		{
		}
   		public function hasEventListener(type:String):Boolean
		{
			return __dispatcher.hasEventListener(type);
		}
		
		public function willTrigger(type:String):Boolean
		{
			return __dispatcher.willTrigger(type);;
		}
		
		public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0.0, useWeakReference:Boolean=false):void
		{
			__dispatcher.addEventListener(type,listener,useCapture,priority,useWeakReference);
		}
		
		public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
		{
			__dispatcher.removeEventListener(type,listener,useCapture);
		}
		
		public function dispatchEvent(event:Event):Boolean
		{
			return __dispatcher.dispatchEvent(event);
		}
		
		public function load(uri:String):void
		{
			__uri = uri;
			
			var bytesloader:URLLoader = new URLLoader(new URLRequest(uri));
			bytesloader.dataFormat = URLLoaderDataFormat.BINARY;
			bytesloader.addEventListener(Event.COMPLETE,onBytesLoaded);
			
		}
		private function onBytesLoaded(evt:Event):void
		{			
			evt.target.removeEventListener(evt.type,onBytesLoaded);
			__byteArray = (evt.target as URLLoader).data as ByteArray;
			checkSwfVersion();
			
		}
		protected function checkSwfVersion():void
		{
			if(checkVersion() > 8)
			{
				var loader:Loader = new Loader();				
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoaderLoaded);	
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
				loader.loadBytes(__byteArray);			
			}
			else//def avm1 content
			{
				AVM_version = 1;	
				handleContent();
			}
		}
		private function onIOError(evt:IOErrorEvent):void
		{
			trace("IO ERROR");
		}
		private function checkVersion():uint
		{
			__byteArray.position = 3;
			return(__byteArray.readByte());
		}
		
		private function onLoaderLoaded(evt:Event):void
		{
			evt.target.removeEventListener(evt.type,onLoaderLoaded);
			var loader:Loader = (evt.target as LoaderInfo).loader;
			AVM_version = (loader.contentLoaderInfo.actionScriptVersion >2)? 2 : 1;
			handleContent();
		}
		
		
		private function onAVM1ContentLoaded(evt:Event):void
		{
			evt.target.removeEventListener(Event.COMPLETE,onAVM1ContentLoaded);
			dispatchEvent(new Event(Event.COMPLETE));
		}
		private function handleContent():void
		{
			var pcontent:Loader
			switch(AVM_version)
			{
				case 2:
					pcontent = new Loader();					
					pcontent.loadBytes(__byteArray);					
					controller = pcontent.content;
					dispatchEvent(new Event(Event.COMPLETE));
					break
				case 1:
//					Log.getLogger(LogType.DATA).warn("Unsupported content was loaded, '"+__uri+"'. \nAll SWFs should be published as ActionScript 3.0.");
					var avm1Loader:AVM1Loader = new AVM1Loader(__uri);
					avm1Loader.addEventListener(Event.COMPLETE,onAVM1ContentLoaded);
					controller = avm1Loader;
					pcontent = avm1Loader.content;
					break		
			}
			content.addChild(pcontent);
		}
		
	}
}